package com.ruoyi.jihuo.api;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.exception.RetryServiceException;
import com.ruoyi.jihuo.domain.JhTmAccount;
import com.taobao.api.ApiException;
import com.taobao.api.DefaultTaobaoClient;
import com.taobao.api.TaobaoClient;
import com.taobao.api.request.DeliveryTemplatesGetRequest;
import com.taobao.api.response.DeliveryTemplatesGetResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map;

import static com.ruoyi.jihuo.constant.TaoApiConstant.*;

/**
 * 调用淘宝api ，只负责调用，不负责业务处理及数据校验
 */
@Component
@Retryable(maxAttempts = 3, backoff = @Backoff(delay = 1000), value = RetryServiceException.class)
public class CallTaoApiService {

    private static final Logger log = LoggerFactory.getLogger(CallTaoApiService.class);

    @Autowired
    @Qualifier("taoApi2")
    private TaoApi taoApiImpl2;

    @Autowired
    @Qualifier("taoApi3")
    private TaoApi taoApiImpl3;

    // todo 默认使用官方
    private TaoApi getTaoApi(String condition) {
        if ("taoApi2".equals(condition)) {
            return taoApiImpl2;
        } else {
            return taoApiImpl3;
        }
    }

    public JSONArray getItemsOnSale(JhTmAccount jhTmAccount, Long pageNo, String orderBy) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("fields", "num_iid,title,num,cid,sold_quantity");
        paramMap.put("page_no", pageNo);
        paramMap.put("page_size", 200L);
        // todo 默认按销量排序 sold_quantity:desc
        paramMap.put("order_by", orderBy);
        String resp = getTaoApi(jhTmAccount.getCondition()).callTaoApi(GET_ITEMS_ON_SALE_API, paramMap, jhTmAccount);
        return JSONObject.parseObject(resp).getJSONArray(GET_ITEMS_ON_SALE_RESPONSE);
    }

    // todo 等会再测
    public JSONObject upShelfItems(JhTmAccount jhTmAccount, Long itemId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("item_id", itemId);
        String resp = getTaoApi(jhTmAccount.getCondition()).callTaoApi(UP_SHELF_ITEMS_API, paramMap, jhTmAccount);
        return JSONObject.parseObject(resp).getJSONObject(UP_SHELF_ITEMS_RESPONSE);
    }

    // todo 等会再测
    public JSONObject downShelfItems(JhTmAccount jhTmAccount, Long itemId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("item_id", itemId);
        String resp = getTaoApi(jhTmAccount.getCondition()).callTaoApi(DOWN_SHELF_ITEMS_API, paramMap, jhTmAccount);
        return JSONObject.parseObject(resp).getJSONObject(DOWN_SHELF_ITEMS_RESPONSE);
    }

    public String getAddProductSchema(JhTmAccount jhTmAccount, Long categoryId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("category_id", categoryId);
        // todo 这个brand_id 是个number，暂时先不传
        //paramMap.put("brand_id", jhTmAccount.getJhBrand());
        String resp = getTaoApi(jhTmAccount.getCondition()).callTaoApi(GET_ADD_PRODUCT_SCHEMA_API, paramMap, jhTmAccount);
        return JSONObject.parseObject(resp).getString(GET_ADD_PRODUCT_SCHEMA_RESPONSE);
    }

    // todo 不清楚什么情况下可以返回同一个货号，什么情况下会报错存在相同的产品
    public JSONObject addProduct(JhTmAccount jhTmAccount, Long categoryId, String data) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("category_id", categoryId);
        // todo 选填值得进行判断，不能简单的赋值或者不赋值
        //paramMap.put("brand_id", jhTmAccount.getJhBrand());
        paramMap.put("xml_data", data);
        String resp = getTaoApi(jhTmAccount.getCondition()).callTaoApi(ADD_PRODUCT_API, paramMap, jhTmAccount);
        JSONObject jsonObject = JSONObject.parseObject(resp);
        return jsonObject;
    }

    public String getProductSchema(JhTmAccount jhTmAccount, Long productId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("product_id", productId);
        String resp = getTaoApi(jhTmAccount.getCondition()).callTaoApi(GET_PRODUCT_SCHEMA_API, paramMap, jhTmAccount);
        return JSONObject.parseObject(resp).getString(GET_PRODUCT_SCHEMA_RESPONSE);
    }

    public JSONObject querySalesVolume(JhTmAccount jhTmAccount, Long itemId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("fields", "sold_quantity,first_starts_time");
        paramMap.put("num_iid", itemId);
        String resp = getTaoApi(jhTmAccount.getCondition()).callTaoApi(QUERY_ITEM_INFO_API, paramMap, jhTmAccount);
        return JSONObject.parseObject(resp).getJSONObject(QUERY_ITEM_INFO_RESPONSE);
    }

    public JSONObject deleteItem(JhTmAccount jhTmAccount, Long itemId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("item_id", itemId);
        String resp = getTaoApi(jhTmAccount.getCondition()).callTaoApi(DELETE_ITEM_API, paramMap, jhTmAccount);
        return JSONObject.parseObject(resp).getJSONObject(DELETE_ITEM_RESPONSE);
    }

    public String getSubmitItemSchema(JhTmAccount jhTmAccount, Long catId, Long spuId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("market", "tmall");
        paramMap.put("cat_id", catId);
        paramMap.put("spu_id", spuId);
        String resp = getTaoApi(jhTmAccount.getCondition()).callTaoApi(GET_SUBMIT_ITEM_SCHEMA_API, paramMap, jhTmAccount);
        return JSONObject.parseObject(resp).getString(GET_SUBMIT_ITEM_SCHEMA_RESPONSE);
    }

    public JSONObject submitItem(JhTmAccount jhTmAccount, Long catId, Long spuId, String schema, JSONObject sourceItemInfoForDistributionDTO) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("market", "tmall");
        paramMap.put("cat_id", catId);
        paramMap.put("spu_id", spuId);
        paramMap.put("schema", schema);
        paramMap.put("source_item_info", sourceItemInfoForDistributionDTO);
        String resp = getTaoApi(jhTmAccount.getCondition()).callTaoApi(SUBMIT_ITEM_API, paramMap, jhTmAccount);
        return JSONObject.parseObject(resp).getJSONObject(SUBMIT_ITEM_RESPONSE);
    }

    public String submitItem(JhTmAccount jhTmAccount, Long catId, Long spuId, String schema) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("market", "tmall");
        paramMap.put("cat_id", catId);
        paramMap.put("spu_id", spuId);
        paramMap.put("schema", schema);
        String resp = getTaoApi(jhTmAccount.getCondition()).callTaoApi(SUBMIT_ITEM_API, paramMap, jhTmAccount);
        log.info("日志收集：catId:{}、spuId:{}、", catId, spuId);
        // 解析JSON响应
        ObjectMapper mapper = new ObjectMapper();
        try {
            JsonNode rootNode = mapper.readTree(resp);
            // 获取error_response节点
            JsonNode errorResponseNode = rootNode.get("error_response");

            if (errorResponseNode != null) {
                int code = errorResponseNode.get("code").asInt();

                if (code == 15) {
                    // 抛出异常，可以自定义异常类型
                    throw new RuntimeException("API调用失败，错误代码: " + code + ", 错误信息: " + errorResponseNode.toPrettyString());
                }
            }
        }catch (Exception e){
            throw new RuntimeException(e);
        }


        return JSONObject.parseObject(resp).getString(SUBMIT_ITEM_RESPONSE);
    }

    /**
     * 账号授权完调用，如果能调通说明授权成功，顺便获取到了店铺品牌id
     *
     * @param jhTmAccount
     * @return
     */
    public JSONObject getItemsAuthorized(JhTmAccount jhTmAccount) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("fields", "brand.vid, brand.name, item_cat.cid, item_cat.name, item_cat.status,item_cat.sort_order,item_cat.parent_cid,item_cat.is_parent,xinpin_item_cat.cid, xinpin_item_cat.name, xinpin_item_cat.status,xinpin_item_cat.sort_order,xinpin_item_cat.parent_cid,xinpin_item_cat.is_parent");
        String resp = getTaoApi(jhTmAccount.getCondition()).callTaoApi(GET_ITEMS_AUTHORIZED_API, paramMap, jhTmAccount);
        return JSONObject.parseObject(resp).getJSONObject(GET_ITEMS_AUTHORIZED_RESPONSE);
    }

    /**
     * 获取店铺运费模版
     * @param url
     * @param appkey
     * @param secret
     * @param sessionKey
     * @return
     * @throws ApiException
     */
    public static com.alibaba.fastjson.JSONObject freightTemplate(String url, String appkey, String secret, String sessionKey) throws ApiException {
        TaobaoClient client = new DefaultTaobaoClient(url, appkey, secret);
        DeliveryTemplatesGetRequest req = new DeliveryTemplatesGetRequest();
        req.setFields("template_id,template_name,created,modified,supports,assumer,valuation,query_express,query_ems,query_cod,query_post");
        DeliveryTemplatesGetResponse rsp = client.execute(req, sessionKey);
        // 提取delivery_template数组数据
        com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(rsp.getBody());
        return jsonObject;
    }

    public JSONObject uploadImage(JhTmAccount jhTmAccount, File file) throws IOException {
        Map<String, Object> paramMap = new HashMap<>();
        byte[] bytes = Files.readAllBytes(file.toPath());
        // 图片分类ID，设置具体某个分类ID或设置0上传到默认分类，只能传入一个分类
        paramMap.put("picture_category_id", 0L);
        paramMap.put("img", bytes);
        paramMap.put("file_path", file.toPath().toString());
        paramMap.put("image_input_title", file.getName());
        String resp = getTaoApi(jhTmAccount.getCondition()).callTaoApi(UPLOAD_PICTURE_API, paramMap, jhTmAccount);
        return JSONObject.parseObject(resp).getJSONObject(UPLOAD_PICTURE_RESPONSE);
    }

    /**
     * 获取用户下所有模板
     *
     * @param jhTmAccount
     * @return
     */
    public JSONObject getDeliveryTemplates(JhTmAccount jhTmAccount) {
        Map<String, Object> paramMap = new HashMap<>();
        String resp = getTaoApi(jhTmAccount.getCondition()).callTaoApi(TAOBAO_DELIVERY_TEMPLATES_GET_API, paramMap, jhTmAccount);
        return JSONObject.parseObject(resp).getJSONObject(TAOBAO_DELIVERY_TEMPLATES_GET_RESPONSE);
    }

}
